\chapter{Il package Util}
Durante lo sviluppo del client Mini-KaZaA sono state individuate una serie di funzioni di utilità varia che logicamente non appartenevano a nessun package visto il compito piuttosto particolare che dovevano svolgere.

\section{Descrittore di file custom}\label{sec:mk_filedescriptor}
%riprendere l'argomento nelle scelte di progetto
Mini-KaZaA utilizza come descrittore dei file una classe che ha definito al suo interno.
Questa classe contiene i metadati utili alla manipolazione dei file e consente di inviare sulla rete un oggetto piuttosto ``agile'' per scambiare informazioni sui files.
\verb|MKFileDescriptor.java| ha proprio queste caratteristiche, a cominciare dai suoi attributi.
\begin{lstlisting}
private String file_name;
private String md5;
private long size;
private String absolute_owner_path;

public MKFileDescriptor(
		String fn,
		String code,
		long s,
		String path
		){
		
	this.file_name = fn;
	this.md5 = code;
	this.size = s;
	this.absolute_owner_path = path;
}
\end{lstlisting}
I parametri che vediamo in questo frammento riguardano tutti la descrizione del file nel computer del suo proprietario. Vedremo come viene calcolato l'md5 in Sezione \ref{sec:md5}.

Mentre i metodi \verb|set| e \verb|get| non sono molto interessanti da illustrare, è importante mostrare come vengono comparati fra di loro gli \emph{MKFileDescriptor}.
\begin{lstlisting}
@Override
public boolean equals(Object obj){
	if(obj instanceof MKFileDescriptor){
		MKFileDescriptor other = (MKFileDescriptor) obj;

		if(this.getMd5().equals(other.getMd5()))
			return true;
	}
	return false;
}

\end{lstlisting}
Da questo piccolo frammento si può notare quanto sia importante l'md5 e che, grazie alla sua bontà, possiamo comparare i vari file con un buon livello di certezza nel confronto.

\section{Calcolo dell'md5}\label{sec:md5}
%inserire controllo per il quote.

\begin{quotation}
L'acronimo MD5 (Message Digest algorithm 5) indica un algoritmo crittografico di hashing realizzato da Ronald Rivest nel 1991 e standardizzato con la RFC 1321.

Questo tipo di codifica prende in input una stringa di lunghezza arbitraria e ne produce in output un'altra a 128 bit (ovvero con lunghezza fissa di 32 valori esadecimali, indipendentemente dalla stringa di input) che può essere usata per calcolare la firma digitale dell'input. La codifica avviene molto velocemente e si presuppone che l'output (noto anche come "MD5 Checksum" o "MD5 Hash") restituito sia univoco (ovvero si ritiene che sia impossibile, o meglio, che sia altamente improbabile ottenere con due diverse stringhe in input una stessa firma digitale in output) e che non ci sia possibilità, se non per tentativi, di risalire alla stringa di input partendo dalla stringa di output (la gamma di possibili valori in output è pari a 16 alla 32esima potenza).\end{quotation} 
%fine del quote

Questa definizione è stata estratta da http://it.wikipedia.org/wiki/Md5 e chiarifica piuttosto bene che cosa intendiamo per \emph{md5}.

In Mini-KaZaA il calcolo di questo particolare codice è affidato alla classe \verb|md5.java|.
Questa classe contiene un solo metodo che prende in input un oggetto di tipo \verb|File|\footnote{Il tipo di dato standard che viene utilizzato da Java per manipolare i dati sul file system.}.

Di seguito riportiamo il codice che salva i risultati in un MessageDigest e legge i primi 1024 byte di un file. Questo limite è stato imposto perchè calcolare l'\emph{md5} di file molto grossi richiede molto tempo. Inoltre, 1024 byte, assicurano un buon livello di diversità fra i vari codici md5.
Successivamente viene convertito il \verb|BigInteger| calcolato in una stringa e restituito.
Se, durante il calcolo, si verifica un errore il metodo ritorna \verb|null|.
\begin{lstlisting}
final int MAX_BYTE = 1024;

try {
	MessageDigest digest = 
		MessageDigest.getInstance("MD5");
		
	InputStream is = new FileInputStream(file);
	
	byte[] buffer = new byte[Constants.MAX_BYTE];
	
	int read = 0;
	while ((read = is.read(buffer)) > 0) {
		digest.update(buffer, 0, read);
	}

	BigInteger bigInt = 
		new BigInteger(1, digest.digest());

	return bigInt.toString(16);

} catch (Exception ex) {
	return null;
}
\end{lstlisting}

\section{Manipolazione delle stringhe}
Il client Mini-KaZaA si trova molto spessoa dover manipolare delle stringhe, soprattutto la loro rappresentazione. Per questo è stata fornita una classe che consente di richiamare metodi pratici per la manipolazione delle stringhe.

Le funzioni di cui si è sentito il bisogno sono state principalmente due.
La prima consente di affermare se una determinata stringa è o meno un indirizzo IP valido.
La seconda invece fornisce una rappresentazione molto più leggibile delle dimensioni dei file traducendo i byte nei vari ordini superiori a seconda della grandezza del file.

Vediamo di seguito i listati dei due metodi con un breve commento.

%controllare che subsubsection faccia sparire il numero, altrimenti non utilizzare nulla
\subsubsection{isInetAddress}
Ecco il metodo che controlla se un indirizzo, \verb|String addr|, passato è veramente un indirizzo IP valido.
\begin{lstlisting}
StringTokenizer tokenizer = new StringTokenizer(addr,".");
boolean result = true;

while(tokenizer.hasMoreTokens()){
	String piece = tokenizer.nextToken();
	
	int pic;
	try{
		pic= Integer.parseInt(piece);
	}
	catch(NumberFormatException ex){return false;}
	if(pic< 0 || pic >255) result = false;
}
return result;
\end{lstlisting}
Questo metodo seziona la stringa di origine in quattro sotto-stringhe e cerca di convertirle in numero.
Se ciò non è possibile significa già che l'indirizzo non è valido.
Se la conversione è riuscita allora bisogna controllare che il numero non superi 255, che è il massimo numero consentito dagli indirizzi ip\footnote{Un indiritto IPv4 è formato da 4 byte separati da un punto e rappresentati in forma decimale $2^8 . 2^8 . 2^8 . 2^8 è appunto 256.$}, o non sia inferiore di 0.

\subsubsection{getRappresentableSize}
Questo è invece il metodo che, preso in input un numero di byte (\verb|long file_size|), restituisce una rappresentazione in stringa più leggibile e facilmente interpretabile.
\begin{lstlisting}
String size = null;
//Bytes
if(file_size < 1024) {
	size = file_size+" bytes";
	if(file_size == 1)
		size = file_size+" byte";
}
else if(file_size < 1024*1024){
	size = 
	((float)file_size / 1024) + " Kb";
}
else if(file_size < 1024*1024*1024){
	size = 
	((float)file_size /
	(1024*1024)) + " Mb";
}
else if(file_size < 1024*1024*1024*1024){
	size = 
	((float)file_size / 
	(1024*1024*1024)) + " Gb";
}
else
	size = 
	((float)file_size / 
	(1024*1024*1024*1024)) + " Tb";

return size;
\end{lstlisting}
Questo metodo è molto semplice. Guarda che soglia supera il numero di byte e poi converte il numero in una stringa molto compatta con l'unità di misura vicino.

\section{Interazione con i file e con i metadati}
Il client Mini-KaZaA ha una forte interazione con i file. Primo motivo fra tutti, il fatto che sia un programma di \emph{file sharing}.
\`{E} stato quindi indispensabile raccogliere in un unico punto tutte le funzioni che riguardano l'interazione dei file, sia a livello di trasmissione sulla rete, sia a livello di salvataggio di informazioni utili al client.

Guardiamo ora che funzioni mette a disposizione.
%public static MKFileDescriptor[] getFilesIntoDirectory(File dir)
\subsection{getFilesIntoDirectory}
Questo metodo prende in input un oggetto di tipo \verb|File| nominato \verb|dir| che identifica una directory e restituisce i file che sono nella directory passata come parametro codificati con l'oggetto \emph{MKFileDescriptor}.
Il metodo si divide in due parti. Nella prima parte esclude dalle rilevazioni sulla directory tutte le sotto-directory creando un array di dimensione \emph{numero elementi nella directory - numero directory}.
\begin{lstlisting}
MKFileDescriptor[] file_array = null;

String[] file_list = dir.list();

int directory = 0;
for (int i = 0; i < file_list.length; i++) {
	File f = new File(file_list[i]);
	if (f.isDirectory()) {
		directory++;
	}
}

file_array = 
new MKFileDescriptor[file_list.length - directory];
\end{lstlisting}
Nella seconda parte invece, converte tutti e soli i file, da \verb|File| a \verb|MKFileDescriptor|.
\begin{lstlisting}
file_array = new MKFileDescriptor[file_list.length - directory];
int index = 0;
for (int i = 0; i < file_list.length; i++) {
	File f = new File(file_list[i]);

	if (!f.isDirectory()) {
		MKFileDescriptor file = new MKFileDescriptor(
				f.getName(),
				md5.getMD5(f),
				f.length(),
				f.getAbsolutePath());
		file_array[index] = file;
		index++;
	}
}
return file_array;
\end{lstlisting}
Alla fine il metodo ritorna l'array calcolato con tutti e soli i file della directory indicata.

%public static MKFileDescriptor[] transformFileToMKFile(File[] files_array)
\subsection{transformFileToMKFile}
Questo metodo prende in input un array di \emph{File}, \verb|files_array|, e si propone di restituire un array di \emph{MKFileDescriptor}.
Il corpo del metodo fa una semplice operazione: scorre tutti i \emph{File} che ci sono in \verb|files_array| e estrae le informazioni che occorrono agli attributi di un oggetto di tipo \emph{MKFileDescriptor}.
Di seguito il codice che esegue queste operazioni.
\begin{lstlisting}
MKFileDescriptor[] mk_files = 
	new MKFileDescriptor[files_array.length];

for (int i = 0; i < files_array.length; i++) {
	String file_name = files_array[i].getName();
	String code = md5.getMD5(files_array[i]);
	long size = files_array[i].length();
	String abs_path = 
		files_array[i].getAbsolutePath();
		
	mk_files[i] = new MKFileDescriptor(
			file_name,
			code,
			size,
			abs_path);

}

return mk_files;
\end{lstlisting}
Esiste anche un altro overload di questo metodo che prende in input un solo \emph{File} e restituisce un solo \emph{MKFileDescriptor} ma le operazioni sono le medesime, quindi non riportiamo più di quanto già visto.

%public static void saveMySharedFiles(OrdinarynodeFiles shared_files)
\subsection{saveMySharedFiles}
Il metodo \verb|saveMySharedFiles| prende come parametro un oggetto di tipo \emph{OrdinarynodeFiles}, \verb|shared_files|, e ``fotografa'' il suo stato all'interno del file \verb|shared.mk|.

Queste operazioni sono state molto semplificate da Java semplicemente dichiarando \emph{Serializable} la classe da scrivere nel file.
Quindi è stato sufficiente scrivere le poche righie, che presentiamo nel listato mostrato successivamente, per scrivere tutto il contenuto dell'oggetto \emph{OrdinarynodeFiles}, in un dato momento, sul file.
\begin{lstlisting}
FileOutputStream file_stream = null;
ObjectOutputStream object_stream = null;

try{
	file_stream = new FileOutputStream(sh_files_save);
	object_stream = new ObjectOutputStream(file_stream);

	object_stream.writeObject(shared_files);
}
\end{lstlisting}

%public static OrdinarynodeFiles loadMySharedFiles(NodeInfo my_infos)
\subsection{loadMySharedFiles}
Il duale del metodo presentato sopra è \verb|loadMySharedFiles| che prende in input un oggetto di tipo \emph{NodeInfo}, \verb|my_infos|, e restituisce l'\emph{OrdinarynodeFiles} contenuto all'interno del file \verb|shared.mk|.

Le affermazioni fatte sopra valgono anche in questo caso. Tutto è stato decisamente semplificato dal Java che si è occupato della fase a \emph{basso livello} di lettura die dati dal file.

Non riportiamo il codice perchè è il duale di quello presentato prima.
